package com.sxj.corejava.code07_面向对象.封装;

/**
 * @author 石小俊
 * 2024年07月15日 14:20
 */
public class Poker {

    private Card[] cards;

    public Poker() {
        // 在此处为一副牌填充54张牌
        cards = new Card[54];
        // 定义花色的范围
        String[] colors = {"黑桃", "红桃", "方块", "梅花"};
        // 定义点数的范围
        String[] nums = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
        // 每一个花色都需要与每一个点数进行组合

        // 定义一个cards数组的初始值,用于为数组的元素赋值,下标从0开始
        int index = 0;

        // 外层循环控制花色
        for (int i = 0; i < colors.length; i++) {
            // 内层循环控制点数
            for (int j = 0; j < nums.length; j++) {
                // 为数组的元素赋值,每一个元素对应一个对象
                // 该对象的两个属性分别对应花色与点数,两两进行组合
                // 每次赋值完元素的值后,index下标自增1
                cards[index++] = new Card(colors[i], nums[j]);
            }
        }

        // 一副扑克牌中还有大小王
        cards[index++] = new Card("大", "王");
        cards[index++] = new Card("小", "王");
    }

    public Card[] getCards() {
        return cards;
    }

    public void setCards(Card[] cards) {
        this.cards = cards;
    }

    public void shuffle() {
        // 定义一个相同长度、相同类型的数组,用于存储洗牌后的数据
        Card[] cards = new Card[54];
        // 为洗牌后的数组进行赋值,其值选自与未洗牌前的数组,且不能重复
        for (int i = 0; i < cards.length; i++) {
            // 随机获取一个0-53的整数
            // 即:随机获取未洗牌前的数组的下标
            int index = (int) (Math.random() * 54);
            // 从未洗牌前的数组中取出对应下标的元素
            Card card = this.cards[index];

            // 随机获取的数组可能在之前已经取出来过了
            // 即:取出的数组元素可能存在重复的
            // 可以从洗牌前数组中取出元素之后,将已取出元素的下标中对应元素的值进行修改
            // 在最终将未洗牌前的元素的值修改为null
            // 再次获取时,如果其值是null,则说明已经取出过了
            while (card == null) {
                // 此时说明当前取出来的元素已经重复了
                // 重新进行随机获取
                index = (int) (Math.random() * 54);
                card = this.cards[index];
            }

            // 如果不重复了,将取出来的元素的值赋值给洗牌后的数组
            cards[i] = card;
            // 将未洗牌前的元素的值修改为null
            this.cards[index] = null;
        }
        // 将洗牌后的数组赋值给成员属性
        this.cards = cards;
    }
}
